/*
 * a rule check engine
 */ 
%option noyywrap yylineno nodefault case-insensitive
%option reentrant 
%option bison-bridge bison-locations
%option stack
%{
#include "rc.tab.hpp"
#include "rc.driver.h"
#include "rc.routine.h"
#define yylvalp yylval_param 
#define yyllocp yylloc_param 
#define ECHO_STATE printf("yystate %d\n",yy_get_previous_state(yyscanner)) 

#define YY_USER_ACTION yyllocp->first_line = yyllocp->last_line = yylineno; \
  yyllocp->first_column = yycolumn; yyllocp->last_column = yycolumn+yyleng-1; \
  yycolumn += yyleng;
%}

%x COMMENT

%%


"/*"            { yy_push_state(COMMENT,yyscanner);}
<COMMENT>"*/"   { yy_pop_state(yyscanner); }
<COMMENT>[ \t\n]  
<COMMENT>[^*]+|.  
<COMMENT><<EOF>>       { yyerror("Unterminated comment" );yyterminate(); } 

\"(\\.|[^\\"])*\" { yylvalp->s = strdup(yytext+1); yylvalp->s[yyleng-2] = 0 ; return STRING;}



[(){}] { return yytext[0];}

  /* comparison */ /* opbit 末三位 EGL E表示相等, G 表示大于 ， L表示小于 */
">"       { yylvalp->opbit = ntype_gt; return CMP;}
"<"       { yylvalp->opbit = ntype_lt; return CMP;}
"<>"|"!=" { yylvalp->opbit = ntype_ne; return CMP;}
"=="      { yylvalp->opbit = ntype_eq; return CMP;}
">="      { yylvalp->opbit = ntype_ge; return CMP;}
"<="      { yylvalp->opbit = ntype_le; return CMP;}

  /* keywords */
"AND" { return AND;}
"OR" { return OR;}
"NOT" { return NOT;}

[a-zA-Z][0-9a-zA-Z]* {yylvalp->s = strdup(yytext);return NAME;}
[-+]?[0-9]+ {yylvalp->n = atoi(yytext);return NUMBER;}
[-+]?[0-9]+"."[0-9]* |
[-+]?[0-9]*"."[0-9]+ {yylvalp->d = atof(yytext);return FLOAT;}

\n { return EOL;}
[ \t] 
. {yyerror("Mystery charactor %c",*yytext); yyterminate();}
%%

#define DRIVER_NAME rc_driver
#define yyg ((struct yyguts_t*)yyscanner)
int DRIVER_NAME::scan_tracing(void* scanner ,bool flag)
{
  yyset_debug(flag,scanner);
}
int DRIVER_NAME::scan_begin()
{
    yyscanner = NULL ;
    yylex_init(&yyscanner);
    if (!yyscanner)
    {
      yyerror("init yyscanner fail");
      return -1;
    }
    scan_tracing(yyscanner,is_trace_scanning);
    if (input_type == 'b') 
    {
        YY_BUFFER_STATE bp;
        bp = yy_scan_string(string.c_str() , yyscanner);
        yy_switch_to_buffer(bp , yyscanner);
        return 0;
    }
    else if (input_type == 'f') 
    {
        if(file.empty() || file == "-")
        {
            yyset_in(stdin, yyscanner);
        }
        else 
        { 
            FILE* in = fopen(file.c_str() , "r");
            if ( !in )
            {
                input_type = ' ';
                yylex_destroy(yyscanner);
                return -1; 
            }
            else
            {
                yyset_in(in , yyscanner);
            }
        }
        return 0;
    }
    return -1;
}

void DRIVER_NAME::scan_end()
{
  if(input_type == 'f')
  {
    FILE* in = yyget_in(yyscanner);
    fclose(in);
  }
  if(input_type == 'b')
  {
    yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner);
  }
  input_type = ' ';
  yylex_destroy(yyscanner);
}
#undef yyg 

